﻿using System;
using System.Drawing;
using System.Windows.Forms;

namespace BGShell.Components
{
    internal class RepeatingHoverProvider : IDisposable
    {
        private Control _control;
        private Boolean _enabled;
        private Point _point;
        private Timer _timer;
        
        public event MouseEventHandler MouseHover;

        public RepeatingHoverProvider(Control control)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }

            _control = control;
            _control.MouseMove += OnMouseMove;
        }

        public bool Enabled
        {
            get { return _enabled; }
            set
            {
                if (_enabled != value)
                {
                    if (_enabled)
                    {
                        if (_timer != null)
                        {
                            _timer.Stop();
                        }

                        if (_control != null)
                        {
                            _control.MouseMove -= OnMouseMove;
                        }
                    }

                    _enabled = value;

                    if (_enabled)
                    {
                        if (_control == null)
                        {
                            throw new ObjectDisposedException(GetType().Name);
                        }
                        _control.MouseMove += OnMouseMove;
                    }
                }
            } 
        }

        public void Dispose()
        {
            if (_control != null)
            {
                _control.MouseMove -= OnMouseMove;
                _control = null;
            }

            if (_timer != null)
            {
                _timer.Dispose();
                _timer = null;
            }

            GC.SuppressFinalize(this);
        }

        private void OnMouseMove(object sender, MouseEventArgs e)
        {
            if (_timer == null)
            {
                _timer = new Timer()
                {
                    Interval = SystemInformation.MouseHoverTime
                };

                _timer.Tick += OnTimerTick;
            }

            _point = e.Location;
            _timer.Start();
        }

        private void OnTimerTick(object sender, EventArgs e)
        {
            _timer.Stop();

            if (_control == null || _control.IsDisposed)
            {
                Dispose();
                return;
            }

            var pos = _control.PointToClient(Control.MousePosition);

            var dx = Math.Abs(_point.X - pos.X);
            var dy = Math.Abs(_point.Y - pos.Y);

            var size = SystemInformation.MouseHoverSize;

            if ((dx < size.Width) && (dy < size.Height))
            {
                var handler = MouseHover;

                if (handler != null)
                {
                    handler(_control, new MouseEventArgs(MouseButtons.None, 0, pos.X, pos.Y, 0));
                }
            }
        }
    }
}